﻿/*
 * Nix PBEM Game Engine.
 * Copyright (C) 2008, Lauris Bukšis-Haberkorns
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Text;

using Nix.PBeM.Engine.DataSources;
using Nix.PBeM.Engine.DataTypes.Orders;
using Nix.PBeM.Engine.DataTypes;

namespace Nix.PBeM.Engine.Process.Orders
{
	class EjectOrder : OrderBase
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="EjectOrder"/> class.
		/// </summary>
		public EjectOrder ()
			: base("EJECT")
		{
			this.Syntax = string.Format("{0} unit-id", this.Keyword);
			this.Description = "Executes if the specified unit is stacked at the first level of stack under your leadership. That unit is forced to unstack if you're the overall stack leader, or is moved out of your substack and just after you if you're stacked below someone else.";
			this.Type = OrderType.Immediate;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="EjectOrder"/> class.
		/// </summary>
		/// <param name="entity">The entity.</param>
		/// <param name="parser">The parser.</param>
		public EjectOrder ( OrderEntity entity, StringLineParser parser )
			: this ()
		{
			this.Entity = entity;
			this.Parser = parser;
		}

		/// <summary>
		/// Create order instance.
		/// </summary>
		/// <param name="entity">The entity.</param>
		/// <returns>Order instance.</returns>
		public override OrderBase Create ( OrderEntity entity, StringLineParser parser )
		{
			return new EjectOrder(entity, parser);
		}

		private Unit follower = null;

		public override void Parse ()
		{
			if ( this.Entity.GetType() != typeof(Unit) )
				throw new OrderParseException("This order can be specified only for unit.");

			string utag = this.Parser.GetOptionalWord();
			if ( string.IsNullOrEmpty(utag) )
				throw new OrderParseException("Unit id not sepcified.");
			this.follower = Engine.Instance.FindUnit(utag);
			if (this.follower == null)
				throw new OrderParseException("Invalid unit id specified.");
		}

		/// <summary>
		/// Order duration.
		/// </summary>
		/// <value></value>
		public override int Duration
		{
			get
			{
				return base.Duration;
			}
			set
			{
				// Allow setting only duration 1 or 0 when executed
				if ( value > 1 || value < 0 )
					base.Duration = 1;
				else
					base.Duration = value;
			}
		}

		public override void Execute ()
		{
			base.Execute();
			
			if (((Unit)this.Entity).MayInterract(this.follower) != Interraction.CanSee)
			{
				this.Entity.AddEventMessage(string.Format("Can not eject unit as there is no such unit in this location."));
				this.ExecutionFailed = true;
				return;
			}
			
			if ( this.follower.Leader != ((Unit)this.Entity) )
			{
				this.Entity.AddEventMessage(string.Format("Can not eject unit as you are not his leader."));
				this.ExecutionFailed = true;
				return;
			}

			// If you are his leader, eject him
			this.follower.Leader = null;
			this.follower.AddEventMessage(string.Format("{0} ejected you from his leadership.", (Unit)this.Entity));
			this.Entity.AddEventMessage(string.Format("Ejected {0} from your leadership.", this.follower));
			this.CompleteExecution();

			// Ejected unit will try to stack under your leader.
			if (((Unit)this.Entity).Leader != null)
			{
				StackOrder.StackUnder(((Unit)this.Entity).Leader, this.follower);
			}
		}
	}
}
